/*
    RoleCall provides a web service that web applications can use to find 
    the roles associated with a user that has been authenticated via OpenID. 
    Also provides a web-based user interface to manage the user roles 
    associated with partner web applications.
    
    Development of this software was supported in part by the David and Lucile 
    Packard Foundation and by the the Office Of Naval Research (ONR) 
     
    Copyright (c) 2012, 
    Monterey Bay Aquarium Research Institute - MBARI ( www.mbari.org )
    Michael Godin ( mikegodin AT users DOT sourceforge DOT net )

    RoleCall is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    RoleCall is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Foobar (see the file COPYING.GPL).  If not, see 
    <http://www.gnu.org/licenses/>.  
*/

package org.mbari.rolecall.client.widget;

import org.mbari.rolecall.client.RoleCallServiceAsync;
import org.mbari.rolecall.client.RoleLister;
import org.mbari.rolecall.client.RoleMap;
import org.mbari.rolecall.model.Relay;
import org.mbari.rolecall.model.Role;
import org.mbari.rolecall.model.UserRole;
import org.mbari.rolecall.model.UserRoleMatch;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.TextBox;

public class AddRoleDialog extends DialogBox {

    TextBox emailBox = new TextBox();

    Label emailLabel = new Label("E-mail:");

    Label emailMatchLabel = new Label("E-mail, use \"%\" for wildcard:");

    TextBox openIDBox = new TextBox();

    Label openIDLabel = new Label("OpenID:");

    RadioButton radioEmailOpenIDRole = new RadioButton("roleType",
            "E-mail and openID");

    RadioButton radioEmailRole = new RadioButton("roleType", "E-mail only");

    RadioButton radioMatchRole = new RadioButton("roleType",
            "E-mail wildcard match");

    Relay relay;

    ListBox roleListBox = new ListBox(true);

    protected RoleLister roleLister;

    TextBox roleRequestBox = new TextBox();

    Label roleRequestLabel = new Label("User's role request:");

    protected RoleCallServiceAsync service;

    public AddRoleDialog(RoleCallServiceAsync service, RoleLister roleLister) {
        super(false);
        this.service = service;
        this.roleLister = roleLister;
        setText("Add Role");
        VerticalFlowPanel vPanel = new VerticalFlowPanel();
        add(vPanel);

        vPanel.add(roleRequestLabel);
        vPanel.add(roleRequestBox);
        roleRequestBox.setEnabled(false);

        vPanel.add(new Label("Role Type to Add:"));
        vPanel.add(radioMatchRole);
        vPanel.add(radioEmailOpenIDRole);
        vPanel.add(radioEmailRole);
        ClickHandler radioClickHandler = new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                updateVisible();
            }
        };
        radioMatchRole.addClickHandler(radioClickHandler);
        radioEmailOpenIDRole.addClickHandler(radioClickHandler);
        radioEmailRole.addClickHandler(radioClickHandler);

        SpacedFlowPanel emailOpenIdPanel = new SpacedFlowPanel();
        vPanel.add(emailOpenIdPanel);
        emailOpenIdPanel.add(emailMatchLabel);
        emailOpenIdPanel.add(emailLabel);
        emailOpenIdPanel.add(emailBox);
        emailOpenIdPanel.add(openIDLabel);
        emailOpenIdPanel.add(openIDBox);

        vPanel.add(new Label("Role(s) To add:"));
        vPanel.add(roleListBox);

        SpacedFlowPanel buttonPanel = new SpacedFlowPanel();
        vPanel.add(buttonPanel);

        buttonPanel.add(new Button("Add Role(s)", new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                addRoles();
            }
        }));

        buttonPanel.add(new Button("Cancel", new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                hide();
            }
        }));
    }

    protected void addRoles() {
        for (int i = 0; i < roleListBox.getItemCount(); ++i) {
            if (-1 == roleListBox.getSelectedIndex()) {
                Window.alert("At least one role should be selected");
                return;
            }
            if (roleListBox.isItemSelected(i)) {
                final String roleName = roleListBox.getItemText(i);
                Role role = RoleMap.get(roleName);
                if (null == role) {
                    if (Window.confirm("The role " + roleName
                            + " appears to be invalid. Continue?")) {
                        continue;
                    } else {
                        return;
                    }
                }
                if (radioMatchRole.getValue()) {
                    UserRoleMatch userRoleMatch = new UserRoleMatch(relay,
                            role, emailBox.getValue());
                    service.submitUserRoleMatch(userRoleMatch,
                            new AsyncCallback<UserRoleMatch>() {
                                @Override
                                public void onFailure(Throwable caught) {
                                    OnFailure.report("Error submitting role "
                                            + roleName, caught);
                                }

                                @Override
                                public void onSuccess(UserRoleMatch result) {
                                    listUserRoleMatch(result);
                                    Window.alert("Added role " + roleName
                                            + " for emails like "
                                            + emailBox.getValue());
                                }
                            });
                } else {
                    final String openID;
                    if (radioEmailOpenIDRole.getValue()) {
                        openID = openIDBox.getValue();
                        if (openID.length() == 0) {
                            Window.alert("Can not specify an empty openID. "
                                    + "Either specify one, or select \"E-mail only\"");
                            return;
                        }
                    } else {
                        openID = null;
                    }
                    UserRole userRole = new UserRole(emailBox.getValue(),
                            openID, relay, role);
                    service.submitUserRole(userRole,
                            new AsyncCallback<UserRole>() {
                                @Override
                                public void onFailure(Throwable caught) {
                                    OnFailure.report("Error submitting role "
                                            + roleName, caught);
                                }

                                @Override
                                public void onSuccess(UserRole result) {
                                    listUserRole(result);
                                    Window.alert("Added role " + roleName
                                            + " for user with email: "
                                            + emailBox.getValue());
                                }
                            });

                }
            }
        }

    }

    protected void listUserRole(UserRole result) {
        roleLister.listUserRole(result);
    }

    protected void listUserRoleMatch(UserRoleMatch result) {
        roleLister.listUserRoleMatch(result);
    }

    public void show(Relay relay, String email, String openID,
            String emailMatch, String existingRoles, String roleRequest) {

        this.relay = relay;
        if (null != email) {
            emailBox.setValue(email);
        } else {
            emailBox.setValue(emailMatch);
        }
        openIDBox.setValue(openID);

        radioEmailOpenIDRole.setValue(null != openID
                || (null == email && null == emailMatch), false);
        radioEmailRole.setValue(null == openID && null != email, false);
        radioMatchRole.setValue(null == openID && null != emailMatch, false);
        updateVisible();

        roleRequestBox.setValue(roleRequest);
        roleRequestLabel.setVisible(null != roleRequest);
        roleRequestBox.setVisible(null != roleRequest);

        roleListBox.clear();
        String[] roles = relay.getRoleNames().split(",");
        roleListBox.setVisibleItemCount(roles.length + 1);
        for (String roleName : roles) {
            roleListBox.addItem(roleName);
        }
        roleListBox.addItem("roleCallRelayAdmin");
        center();
    }

    protected void updateVisible() {
        emailMatchLabel.setVisible(radioMatchRole.getValue());
        emailLabel.setVisible(!radioMatchRole.getValue());
        emailBox.setVisible(true);
        openIDLabel.setVisible(radioEmailOpenIDRole.getValue());
        openIDBox.setVisible(radioEmailRole.getValue());
        openIDBox.setVisible(radioEmailOpenIDRole.getValue());
    }
}
